//
// SoapTrace.Net - A soap message monitoring utility. 
//
// Copyright (C) 2005 Matthew Ward
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
// Matthew Ward (mrward@users.sourceforge.net)

using SoapTrace.Core.Communication;
using System.Runtime.Remoting;
using System;
using System.IO;

namespace SoapTrace.Core.Diagnostics
{
	/// <summary>
	/// Manages the <see cref="SoapMessageLogger"/>.
	/// </summary>
	public class SoapMessageLoggingManager
	{
		/// <summary>
		/// The soap message logger.
		/// </summary>
		private ISoapMessageLogger m_SoapMessageLogger;
		
		/// <summary>
		/// Reference to the logger config.
		/// </summary>
		private SoapMessageLoggerConfiguration m_Config;
		
		/// <summary>
		/// The default log file folder.
		/// </summary>
		private static readonly string m_DefaultLogFileFolder = 
			Path.Combine( Environment.GetFolderPath( Environment.SpecialFolder.LocalApplicationData ), 
				@"SoapTrace.Net\Log" );		
		
		/// <summary>
		/// Creates a new instance of the 
		/// <see cref="SoapMessageLoggingManager"/>.
		/// </summary>
		/// <param name="config">The config for the soap message
		/// logger.</param>
		public SoapMessageLoggingManager( SoapMessageLoggerConfiguration config )
		{
			m_Config = config;
						
			if( ( config.TypeName.Length > 0 ) && ( config.AssemblyName.Length > 0 ) )
			{
				CreateSoapMessageLogger( config.TypeName, config.AssemblyName, config.Enabled, config.Folder );
			}
			else
			{
				Logger.LogDebug( "SoapMessageLogger type and assembly name not specified in config." );
			}
		}
		
		/// <summary>
		/// Gets or sets logging enabled flag.
		/// </summary>
		public bool LoggingEnabled
		{
			get
			{
				return m_Config.Enabled;
			}
			
			set
			{
				m_Config.Enabled = value;
				
				if( m_SoapMessageLogger != null )
				{
					m_SoapMessageLogger.Enabled = value;
				}				
			}
		}
		
		/// <summary>
		/// Gets or sets the folder used for logging.
		/// </summary>
		public string LogFolder
		{
			get
			{
				return m_Config.Folder;
			}
			
			set
			{
				lock( m_Config )
				{
					SetLogFileFolder( value );
				}
			}
		}
		
		/// <summary>
		/// Logs the soap request and response.
		/// </summary>
		/// <param name="serverAddressFilter">Remote server's ip address
		/// or host name.</param>
		/// <param name="serverPortFilter">Remote server's port.</param>
		/// <param name="requestAndResponse">Soap request and response
		/// to log.</param>
		public void Log( string serverAddressFilter, int serverPortFilter, SoapRequestAndResponse requestAndResponse )
		{
			if( m_SoapMessageLogger != null )
			{
				if( m_SoapMessageLogger.Enabled )
				{
					// Ensure that the folder cannot change whilst
					// we are logging on another thread.
					
					lock( m_Config ) 
					{
						m_SoapMessageLogger.Log( serverAddressFilter, serverPortFilter, requestAndResponse );
					}
				}
			}
		}
		
		/// <summary>
		/// Creates the ISoapMessageLogger type specified in the config.
		/// </summary>
		/// <param name="typeName">The type name of the logger.</param>
		/// <param name="assemblyName">The assembly containing the 
		/// logger.</param>
		/// <param name="enabled">Enables/disables logging.</param>
		/// <param name="folder">The log file folder.</param>
		private void CreateSoapMessageLogger( string typeName, string assemblyName, bool enabled, string folder )
		{
			Logger.Log( "Creating SoapMessageLogger..." );
			
			try
			{
				ObjectHandle MessageLoggerObject = Activator.CreateInstance( assemblyName, typeName );
				
				ISoapMessageLogger MessageLogger = MessageLoggerObject.Unwrap( ) as ISoapMessageLogger;

				if( MessageLogger != null )
				{
					Logger.Log( String.Concat( "Created SoapMessageLogger '", typeName, ", ", assemblyName, "'." ) );
			
					m_SoapMessageLogger = MessageLogger;
					m_SoapMessageLogger.Enabled = enabled;
					
					SetLogFileFolder( folder );
				}
				else
				{
					Logger.LogError( 
						String.Concat( "SoapMessageLogger '", typeName, ", ", assemblyName,
						"' does not implement the ISoapMessageLogger interface." ) );
				}
			}
			catch( FileNotFoundException Ex )
			{
				Logger.LogError( String.Concat( "Could not create '", typeName, ", ", assemblyName,  "'.  ", Ex.ToString( ) ) );
			}
			
			Logger.Log( "Created SoapMessageLogger." );
		}
		
		/// <summary>
		/// Sets the log file folder.
		/// </summary>
		/// <remarks>If the log file folder is an empty string
		/// it is set to the default folder.</remarks>
		/// <param name="folder">The log file folder.</param>
		private void SetLogFileFolder( string folder )
		{
			if( folder.Length == 0 )
			{
				folder = m_DefaultLogFileFolder;
			}
			
			m_Config.Folder = folder;
				
			if( m_SoapMessageLogger != null )
			{
				m_SoapMessageLogger.Folder = folder;
			}
		}
	}
}
